package com.example.apisimpledy.service.impl;

import com.example.apisimpledy.entity.dto.*;
import com.example.apisimpledy.repository.*;
import com.example.apisimpledy.service.VideoService;
import com.example.apisimpledy.utils.OssUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.image.BufferedImage;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class VideoServiceImpl implements VideoService {

    private static final Logger logger = LoggerFactory.getLogger(VideoServiceImpl.class);

    @Autowired
    private VideoRepository videoRepository;

    @Autowired
    private MyUserRepository myUserRepository;
    @Autowired
    private VideoLikeRepository videoLikeRepository;
    @Autowired
    private CommentRepository commentRepository;
    @Autowired
    private VideoViewRepository videoViewRepository;

    @Autowired
    private OssUtil ossUtil;

    @Override
    public Video uploadVideo(MultipartFile videoFile) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        Optional<MyUser> userOptional = myUserRepository.findByUsernameOrEmail(username, username);

        if (userOptional.isEmpty()) {
            throw new RuntimeException("User not found!");
        }

        MyUser user = userOptional.get();
        Long userId = user.getId();

        // Step 1: Save video record without URLs
        Video video = new Video();
        video.setTitle(videoFile.getOriginalFilename())
                .setDescription("Video uploaded by user " + userId)
                .setMyUser(user)
                .setUploadTime(Timestamp.from(Instant.now()))
                .setLikes(0)
                .setViews(0);
        Video savedVideo = videoRepository.saveAndFlush(video); // saveAndFlush to get the generated ID immediately
        Long videoId = savedVideo.getId();

        // Step 2: Upload video file and thumbnail
        String videoUrl = ossUtil.uploadFile(videoFile, String.valueOf(userId), String.valueOf(videoId), "video");

        BufferedImage thumbnail;
        try {
            thumbnail = ossUtil.grabFirstFrame(videoFile);
        } catch (Exception e) {
            throw new RuntimeException("Failed to extract thumbnail from video", e);
        }
        String pictureUrl = ossUtil.uploadImage(thumbnail, String.valueOf(userId), String.valueOf(videoId), "picture");

        // Get video duration
        int duration;
        try {
            duration = ossUtil.getVideoDuration(videoFile);
        } catch (Exception e) {
            throw new RuntimeException("Failed to get video duration", e);
        }

        // Step 3: Update video record with URLs and duration
        savedVideo.setVideoPath(videoUrl)
                .setThumbnailPath(pictureUrl)
                .setDuration(duration);
        videoRepository.save(savedVideo);

        // Add "uploader" role to user if not already present
        Set<String> roles = user.getRoles();
        if (!roles.contains("uploader")) {
            roles.add("uploader");
            user.setRoles(roles);
            myUserRepository.save(user);
        }

        return savedVideo;
    }

    @Override
    public void deleteVideo(Long videoId) {
        Optional<Video> videoOptional = videoRepository.findById(videoId);
        if (videoOptional.isEmpty()) {
            throw new RuntimeException("Video not found!");
        }

        Video video = videoOptional.get();
        String videoPath = video.getVideoPath();
        String thumbnailPath = video.getThumbnailPath();

        // 删除OSS上的视频文件和缩略图
        try {
            ossUtil.deleteFile(videoPath);
            ossUtil.deleteFile(thumbnailPath);
        } catch (RuntimeException e) {
            logger.error("Error deleting files from OSS", e);
            throw e;
        }

        // 删除数据库中的记录
        videoRepository.deleteById(videoId);
        logger.info("Deleted video with ID: {}", videoId);
    }

    @Override
    public List<Video> getMyVideos(int page, int size) {
        MyUser user = getCurrentUser();
        Pageable pageable = PageRequest.of(page, size);
        Page<Video> videoPage = videoRepository.findByMyUserId(user.getId(), pageable);
        return videoPage.getContent();
    }

    @Override
    @Transactional
    public String likeVideo(Long videoId) {
        MyUser currentUser = getCurrentUser();
        Long userId = currentUser.getId();
        System.out.println(currentUser);
        if (!videoLikeRepository.existsByMyUserIdAndVideoId(userId, videoId)) {
            Video video = videoRepository.findById(videoId).orElseThrow(() -> new RuntimeException("Video not found"));
            VideoLike newLike = new VideoLike().setVideo(video).setMyUser(currentUser);
            videoLikeRepository.save(newLike);
            video.setLikes(video.getLikes() + 1);
            videoRepository.save(video);
            return "视频成功点赞";
        }
        return "您已经点赞过这个视频";
    }

    @Override
    public List<Video> getRecommendedVideos() {
        MyUser user = getCurrentUser();
        return videoRepository.findRecommendedVideosExcludingViewedByUser(user.getId());
    }

    @Override
    public void addComment(Long videoId, String commentText) {
        MyUser user = getCurrentUser();
        Optional<Video> videoOptional = videoRepository.findById(videoId);
        if (videoOptional.isEmpty()) {
            throw new RuntimeException("Video not found!");
        }

        Video video = videoOptional.get();
        Comment comment = new Comment();
        comment.setVideo(video);
        comment.setMyUser(user);
        comment.setContent(commentText);
        comment.setCreatedAt(Timestamp.from(Instant.now()));

        commentRepository.save(comment);
    }

    @Override
    public List<Comment> getComments(Long videoId) {
        Optional<Video> videoOptional = videoRepository.findById(videoId);
        if (videoOptional.isEmpty()) {
            throw new RuntimeException("Video not found!");
        }

        return commentRepository.findByVideoId(videoId);
    }


    @Override
    public void recordView(Long videoId) {
        MyUser user = getCurrentUser();
        Optional<Video> videoOptional = videoRepository.findById(videoId);
        if (videoOptional.isEmpty()) {
            throw new RuntimeException("Video not found!");
        }

        Video video = videoOptional.get();

        // 检查用户是否已经浏览过该视频
        boolean alreadyViewed = videoViewRepository.existsByMyUserAndVideo(user, video);
        if (!alreadyViewed) {
            VideoView videoView = new VideoView();
            videoView.setMyUser(user);
            videoView.setVideo(video);
            videoView.setViewTime(Timestamp.from(Instant.now()));

            videoViewRepository.save(videoView);

            // 增加视频的views字段
            video.setViews(video.getViews() + 1);
            videoRepository.save(video);
        }
    }

    private MyUser getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        String username = authentication.getName();
        Optional<MyUser> userOptional = myUserRepository.findByUsernameOrEmail(username, username);

        if (userOptional.isEmpty()) {
            throw new RuntimeException("User not found!");
        }

        return userOptional.get();
    }
}
